﻿/*
 * ====================================================================
 * Copyright (c) 2000-2006 MineHe.  All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at http://www.minehe.net/projects/miucos/terms.aspx.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://www.minehe.net/projects/miucos/ or 
 * http://code.google.com/p/miucos/.
 * 
 * WARNNING!!!!!!
 * YOU CAN NOT USE THIS CODE FILE OR ANY CODES IN MIUCOS FILES FOR COMMERCIAL
 * SYSTEM OR PURPOSE.
 * ====================================================================
 */

using System;
using System.Collections.Generic;
using System.Text;

namespace minehe.miucos.common
{
	#region Result Codes Declare

	/// <summary>
	/// 结果代码声明类。
	/// </summary>
	/// <remarks>
	/// 该类声明常用的结果代码。
	/// </remarks>
	public partial class ResultCodes
	{
		#region Result Codes Declares

		#region Common Result Codes ( 0 - 255 )

		/// <summary>
		/// 一般性执行失败。该状态码用于不详细或未知的失败原因。
		/// 在知道确切失败原因情况下，方法应该返回具体的状态码。
		/// </summary>
		public const int RC_FAILURE = 0;
		/// <summary>
		/// 执行成功
		/// </summary>
		public const int RC_SUCC = 1;
		/// <summary>
		/// 方法执行中抛出了异常
		/// </summary>
		public const int RC_EXCEPTION = 2;
		/// <summary>
		/// 方法不支持该操作
		/// </summary>
		public const int RC_NOTSUPPORT = 3;
		/// <summary>
		/// 方法没有实现，是预留方法
		/// </summary>
		public const int RC_NOTIMPL = 4;
		/// <summary>
		/// 方法参数非法
		/// </summary>
		public const int RC_ARGUMENT = 5;
		/// <summary>
		/// 对象/值是空(null)
		/// </summary>
		public const int RC_ISNULL = 6;
		/// <summary>
		/// 超出索引边界
		/// </summary>
		public const int RC_INDEXOFOUTRANGE = 7;
		/// <summary>
		/// 数据类型转换失败
		/// </summary>
		public const int RC_INVALIDCAST = 8;
		/// <summary>
		/// 指定键值不存在
		/// </summary>
		public const int RC_KEYNOTFOUND = 9;
		/// <summary>
		/// 指定键值已经存在
		/// </summary>
		public const int RC_KEYEXISTS = 10;
		/// <summary>
		/// 目标不存在
		/// </summary>
		public const int RC_NOTEXISTS = 11;
		/// <summary>
		/// 目标已经存在
		/// </summary>
		public const int RC_EXISTS = 12;
		/// <summary>
		/// 集合是空集合（即没有任何元素存在的集合）
		/// </summary>
		public const int RC_EMPTYCOLLECTION = 13;
		/// <summary>
		/// 尚未初始化完毕
		/// </summary>
		public const int RC_UNINIT = 14;
		/// <summary>
		/// 该方法仅能调用一次并且已经被调用过一次
		/// </summary>
		public const int RC_CALLONCE = 15;
		/// <summary>
		/// 访问被拒绝
		/// </summary>
		public const int RC_ACCESSDENIE = 16;
		/// <summary>
		/// 值是只读的，不能写入
		/// </summary>
		public const int RC_READONLY = 17;
		/// <summary>
		/// 等待
		/// </summary>
		public const int RC_PENDING = 18;

		#endregion

		#endregion
	}

	#endregion

	#region Result Class

	/// <summary>
	/// 结果类。
	/// 结果类用于方法返回结果，通过结果类可以区分方法正常的返回值和方法执行的状态返回值。
	/// </summary>
	/// <threadsafety instance="true" static="true"/>
	/// <remarks>
	/// 方法返回应该统一返回<see cref="Result{TValue}"/>或其子类作为方法返回值。但某些不需要
	/// 返回数据的方法可以直接返回方法结果，比如IsExists(xxx)类型方法可以直接返回bool值，而不
	/// 需要返回<see cref="Result{TValue}"/>结果。结果类的主要作用是将正常的返回数据与方法执行
	/// 的状态(成功？失败？...)区分开。
	/// <para>
	/// 举例来说，bool IsExists(string a_userID)方法，该方法用于判断指定ID的用户是否在数据库中存在。
	/// 对于这个方法来说，其方法返回的只有两种值：True或False。True和False作为结果数据是方法
	/// 在正常执行后应该返回的结果，其结果直接对应到用户ID是否存在这个事实。那么，方法返回
	/// 的结果应该是与用户ID本身是否存在这个客观事实相联系的。考虑该方法的实现代码，通常的
	/// 实现代码如下：
	/// <code>
	/// public bool IsExists(string a_userID)
	/// {
	///			ASDebug.Assert((a_userID!=null) &amp;&amp; (a_userID!=""));
	/// 
	///			try
	///			{
	///				//Execute sql to determines whether the user id is exists
	///				string l_sql = "SELECT COUNT(*) FROM TAB_USER WHERE USR_ID='" + a_userID + "'";
	///				return (int)this.ExecuteSQLScalar(l_sql)&gt;0?true:false;
	///			}
	///			catch(Exception)
	///			{
	///				return false;
	///			}
	/// }
	/// </code>
	/// 现在我们看到了try {...} catch(Exception) {...} 处理异常的方式。前面的True和False问题出现了。
	/// True/False是表明指定用户ID是否存在的结果数据，然而如果在方法执行过程中发生了异常，
	/// 比如数据库断开或者网络出现故障等等，这些异常往往是必须在代码中处理和拦截的。当异常
	/// 出现时，如果按照上面代码的逻辑返回False，那么调用方法的一方将得到False值，而False值
	/// 本身应该是表明该用户ID不存在这个事实，调用方从单纯的True/False无法得知方法执行中是
	/// 因为触发了异常而导致返回False，并不是表示该用户ID真的不存在。
	/// </para>
	/// <para>
	/// 还有一种不恰当的但被普遍使用的返回值处理策略。看如下代码范例：
	/// <code>
	/// public int GetOrdersCount()
	/// {
	///			try
	///			{
	///				//Execute sql to get the orders count
	///				string l_sql = "SELECT COUNT(*) FROM TAB_ORDER";
	///				return (int)this.ExecuteSQLScalar(l_sql);
	///			}
	///			catch(Exception)
	///			{
	///				return -1;
	///			}
	/// }
	/// </code>
	/// 这个GetOrdersCount()方法用于获取数据库中当前的订单数量。我们同样观察到在这个典型的
	/// try {...} catch(Exception) {...} 处理异常的结构中，当方法遇到异常时将返回一个预定义的错误
	/// 值-1。实际上，这个方法将正常的返回值(0..N)数据与发生错误时的状态值-1混淆在一起。这种
	/// 方法编写的问题在于调用方法时，调用方必须很清楚并且已经对各种错误状态返回值进行了
	/// 处理，如果调用方没有考虑到错误状态值，那么将可能导致隐藏的BUG。
	/// </para>
	/// <para>
	/// 结果类的引入强制性的把正常返回数据与方法执行状态区分开，这将改善这种比较混乱的返回值
	/// 处理策略。
	/// </para>
	/// <para>
	/// 调用者对于返回<see cref="Result{TValue}"/>的方法，应该首先判断结果类实例的状态成员
	/// <see cref="Result{TValue}.ResultCode"/>，通过该成员值可以知道方法执行是否成功，只有
	/// 在执行成功情况下才应该获取方法返回数据。如果不判断得到的结果类实例的方法状态成员，
	/// 而直接去获取返回数据则可能得到一个异常或者非法的数据，从而导致系统执行出现BUG或者
	/// 其他问题。
	/// </para>
	/// <para>
	/// 结果类实例的使用应该是一次性的，不要尝试去保存结果类或者将结果类序列化或者将结果类
	/// 数据/状态作为持久性数据使用，这违背结果类设计的初衷，虽然技术上可以这样去做。
	/// 结果类本身虽然目前是线程安全类型的，结果类实例成员必须通过构造方法才能赋值，
	/// 所有实例属性和方法都保证不会更改成员状态和值。
	/// 但是，结果类本身是为一次性使用而设计的，结果类不保证在将来也是线程安全类型，而且您
	/// 应该在获得方法返回的结果类实例并使用以后就废弃该结果实例。尽量避免并发使用结果类实例。
	/// </para>
	/// <para>
	/// 结果类不应该被用于分支代码选择，方法不要将结果类的状态码作为传递给调用方的分支
	/// 路径的条件，结果类的唯一作用就是将方法执行状态与正常返回数据合并在一个实例类中。
	/// 仅用于合理的获取方法执行状态并在成功状态下获取返回数据。
	/// </para>
	/// <para>
	/// 结果类主要成员是<see cref="Result{TValue}.ResultCode"/>和
	/// <see cref="Result{TValue}.ReturnValue"/>，<see cref="Result{TValue}.ResultCode"/>成员是方法
	/// 返回时的方法执行状态。
	/// <see cref="Result{TValue}.ResultCode"/>只有两种，一种是<see cref="ResultCodes.RC_SUCC"/>
	/// 代表方法执行成功；剩下所有的其他状态码都表示方法执行不成功，并揭示方法执行不成功的
	/// 具体细节，每一个状态码都唯一对应一种执行失败的具体情况。永远不要再声明表示执行成功
	/// 的状态码。
	/// </para>
	/// </remarks>
	/// <example>
	/// 使用<see cref="Result{TValue}"/>作为返回值的方法范例：
	/// <code>
	/// public Result&lt;int&gt; GetOrdersCount()
	/// {
	///		try
	///		{
	///			//Execute sql to get the orders count
	///			string l_sql = "SELECT COUNT(*) FROM TAB_ORDER";
	///			return new SucceedResult&lt;int&gt;((int)this.ExecuteSQLScalar(l_sql));
	///		}
	///		catch(Exception ex)
	///		{
	///			return ExceptionResult&lt;int&gt;(ex);
	///		}
	/// }
	/// </code>
	/// <para>
	/// 调用GetOrdersCount代码的处理范例：
	/// <code>
	/// ...
	/// Result&lt;int&gt; l_r = GetOrdersCount();
	/// if(l_r.IsSucceed)
	/// {
	///		//Execution succeed
	///		int l_ordersCount = l_r.ReturnValue;
	///		...
	/// }
	/// else
	/// {
	///		//Failure
	///		...
	/// }
	/// ...
	/// </code>
	/// </para>
	/// </example>
	[SerializableAttribute()]
	public partial class Result<TValue>
	{
		#region Native Class Members

		private int m_resultCode;
		private TValue m_returnValue;
		private object m_additionObject;

		#endregion

		#region Constructors / Deconstructors

		/// <summary>
		/// 缺省的构造方法。
		/// </summary>
		/// <postcondition>
		/// <see cref="Result{TValue}.ResultCode"/>值为<see cref="ResultCodes.RC_SUCC"/>
		/// <para><see cref="Result{TValue}.ReturnValue"/>值为null</para>
		/// <para><see cref="Result{TValue}.AdditionObject"/>值为null</para>
		/// </postcondition>
		public Result()
		{
			this.m_resultCode = ResultCodes.RC_SUCC;
			this.m_returnValue = default(TValue);
			this.m_additionObject = null;
		}

		/// <summary>
		/// 带指定状态码的构造方法，本构造方法仅用于失败状态
		/// </summary>
		/// <param name="a_resultCode">状态码</param>
		/// <postcondition>
		/// <see cref="Result{TValue}.ResultCode"/>值为a_resultCode值
		/// <para><see cref="Result{TValue}.ReturnValue"/>值为null</para>
		/// <para><see cref="Result{TValue}.AdditionObject"/>值为null</para>
		/// </postcondition>
		public Result(int a_resultCode)
		{
			this.m_resultCode = a_resultCode;
			this.m_returnValue = default(TValue);
			this.m_additionObject = null;
		}

		/// <summary>
		/// 带指定状态码、返回数据和附加信息/对象的构造方法。
		/// </summary>
		/// <param name="a_resultCode">状态码</param>
		/// <param name="a_returnValue">返回数据</param>
		/// <param name="a_additionObject">附加信息或对象</param>
		/// <postcondition>
		/// <see cref="Result{TValue}.ResultCode"/>值为a_resultCode值
		/// <para><see cref="Result{TValue}.ReturnValue"/>值为a_returnValue值，可接受null值</para>
		/// <para><see cref="Result{TValue}.AdditionObject"/>值为a_additionObject值，可接受null值</para>
		/// </postcondition>
		public Result(int a_resultCode, TValue a_returnValue, object a_additionObject)
		{
			this.m_resultCode = a_resultCode;
			this.m_returnValue = a_returnValue;
			this.m_additionObject = a_additionObject;
		}

		/// <summary>
		/// 析构方法
		/// </summary>
		~Result()
		{
		}

		#endregion

		#region Property Getters/Setters

		/// <summary>
		/// 获取当前结果类实例的状态码。
		/// </summary>
		public int ResultCode
		{
			get
			{
				return this.m_resultCode;
			}
		}

		/// <summary>
		/// 获取当前结果类实例的返回数据。如果状态码不是成功状态
		/// 则返回数据可能是非法值（依赖于方法定义规则）。
		/// </summary>
		/// <precondition>
		/// 在获取该返回数据之前应该首先判断
		/// 状态码<see cref="Result{TValue}.ResultCode"/>是否是执行成功状态或者判断
		/// <see cref="Result{TValue}.IsSucceed"/>是否等于true。一般情况下，只有当
		/// 状态是执行成功<see cref="ResultCodes.RC_SUCC"/>或<see cref="Result{TValue}.IsSucceed"/>
		/// 值为true时，才应该有返回值。
		/// </precondition>
		public TValue ReturnValue
		{
			get
			{
				return this.m_returnValue;
			}
		}

		/// <summary>
		/// 获取当前结果类实例的状态码<see cref="Result{TValue}.ResultCode"/>是否是执行成功状态。
		/// </summary>
		/// <remarks>
		/// 只有当<see cref="Result{TValue}.ResultCode"/>=<see cref="ResultCodes.RC_SUCC"/>时才表示
		/// 当前结果类实例的状态是执行成功状态。
		/// </remarks>
		public bool IsSucceed
		{
			get
			{
				return (this.ResultCode == ResultCodes.RC_SUCC);
			}
		}

		/// <summary>
		/// 获取当前结果类实例的附加信息/对象。该附加信息或对象由具体方法环境
		/// 来决定和定义。请参见具体方法返回说明以获取附加信息或对象的说明。
		/// 如果对未说明此信息的方法返回结果获取该值，则将得到空值null返回。
		/// </summary>
		public object AdditionObject
		{
			get
			{
				return this.m_additionObject;
			}
		}

		#endregion
	}

	#endregion

	#region Extend Result Classes

	/// <summary>
	/// 本类是<see cref="Result{TValue}"/>结果类的<see cref="System.Object"/>具体类型子类，
	/// 本类用于仅需要状态返回的情况。
	/// </summary>
	[SerializableAttribute()]
	public class StatusResult : Result<object>
	{
		#region Constructors / Deconstructors

		/// <summary>
		/// 带状态码的无数据返回的构造方法
		/// </summary>
		/// <param name="a_resultCode">状态码</param>
		public StatusResult(int a_resultCode)
			: base(a_resultCode)
		{
		}

		/// <summary>
		/// 带状态码和附加对象信息的构造方法
		/// </summary>
		/// <param name="a_resultCode">状态码</param>
		/// <param name="a_additionObject">附加对象信息</param>
		public StatusResult(int a_resultCode, object a_additionObject)
			: base(a_resultCode, null, a_additionObject)
		{
		}

		#endregion
	}

	/// <summary>
	/// 本类是<see cref="StatusResult"/>结果类的表示执行成功状态的子类。
	/// </summary>
	[SerializableAttribute()]
	public class SucceedStatusResult : StatusResult
	{
		#region Constructors / Deconstructors

		/// <summary>
		/// 无返回数据的构造方法。
		/// </summary>
		public SucceedStatusResult()
			: base(ResultCodes.RC_SUCC)
		{
		}

		#endregion
	}

	/// <summary>
	/// 本类是<see cref="Result{TValue}"/>结果类的表示执行成功状态的子类。
	/// </summary>
	[SerializableAttribute()]
	public class SucceedResult<TValue> : Result<TValue>
	{
		#region Constructors / Deconstructors

		/// <summary>
		/// 无返回数据的构造方法。
		/// </summary>
		public SucceedResult()
			: base(ResultCodes.RC_SUCC)
		{
		}

		/// <summary>
		/// 带返回数据的构造方法。
		/// </summary>
		/// <param name="a_returnValue">返回数据</param>
		public SucceedResult(TValue a_returnValue)
			: base(ResultCodes.RC_SUCC, a_returnValue, null)
		{
		}

		#endregion
	}

	/// <summary>
	/// 本类是<see cref="Result{TValue}"/>结果类的专针对异常抛出的结果类。
	/// </summary>
	/// <seealso cref="Result{TValue}"/>
	[SerializableAttribute()]
	public class ExceptionResult : Result<object>
	{
		#region Constructors / Deconstructors

		/// <summary>
		/// 不带内部异常信息的构造方法，
		/// 状态码将是异常失败状态<see cref="ResultCodes.RC_EXCEPTION"/>且无返回数据。
		/// </summary>
		public ExceptionResult()
			: base(ResultCodes.RC_EXCEPTION, null, null)
		{
		}

		/// <summary>
		/// 带内部异常信息的构造方法，
		/// 状态码将是异常失败状态<see cref="ResultCodes.RC_EXCEPTION"/>且无返回数据。
		/// </summary>
		public ExceptionResult(Exception a_innerException)
			: base(ResultCodes.RC_EXCEPTION, null, a_innerException)
		{
		}

		#endregion
	}

	/// <summary>
	/// 本类是<see cref="Result{TValue}"/>结果类的专针对异常抛出的结果类。
	/// </summary>
	/// <seealso cref="Result{TValue}"/>
	[SerializableAttribute()]
	public class ExceptionResult<TValue> : Result<TValue>
	{
		#region Constructors / Deconstructors

		/// <summary>
		/// 不带内部异常信息的构造方法，
		/// 状态码将是异常失败状态<see cref="ResultCodes.RC_EXCEPTION"/>且无返回数据。
		/// </summary>
		public ExceptionResult()
			: base(ResultCodes.RC_EXCEPTION, default(TValue), null)
		{
		}

		/// <summary>
		/// 带内部异常信息的构造方法，
		/// 状态码将是异常失败状态<see cref="ResultCodes.RC_EXCEPTION"/>且无返回数据。
		/// </summary>
		public ExceptionResult(Exception a_innerException)
			: base(ResultCodes.RC_EXCEPTION, default(TValue), a_innerException)
		{
		}

		#endregion
	}

	#endregion
}
